home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C25 / PaperScissorsRock.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  2.8 KB  |  134 lines

  1. //: C25:PaperScissorsRock.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Demonstration of multiple dispatching
  7. #include "../purge.h"
  8. #include <iostream>
  9. #include <vector>
  10. #include <algorithm>
  11. #include <cstdlib>
  12. #include <ctime>
  13. using namespace std;
  14.  
  15. class Paper;
  16. class Scissors;
  17. class Rock;
  18.  
  19. enum Outcome { win, lose, draw };
  20.  
  21. ostream& 
  22. operator<<(ostream& os, const Outcome out) {
  23.   switch(out) {
  24.     default:
  25.     case win: return os << "win";
  26.     case lose: return os << "lose";
  27.     case draw: return os << "draw";
  28.   }
  29. }
  30.  
  31. class Item {
  32. public:
  33.   virtual Outcome compete(const Item*) = 0;
  34.   virtual Outcome eval(const Paper*) const = 0;
  35.   virtual Outcome eval(const Scissors*) const= 0;
  36.   virtual Outcome eval(const Rock*) const = 0;
  37.   virtual ostream& print(ostream& os) const = 0;
  38.   virtual ~Item() {}
  39.   friend ostream& 
  40.   operator<<(ostream& os, const Item* it) {
  41.     return it->print(os);
  42.   }
  43. };
  44.  
  45. class Paper : public Item {
  46. public:
  47.   Outcome compete(const Item* it) {
  48.     return it->eval(this);
  49.   }
  50.   Outcome eval(const Paper*) const {
  51.     return draw;
  52.   }
  53.   Outcome eval(const Scissors*) const {
  54.     return win;
  55.   }
  56.   Outcome eval(const Rock*) const {
  57.     return lose;
  58.   }
  59.   ostream& print(ostream& os) const {
  60.     return os << "Paper   ";
  61.   }
  62. };
  63.  
  64. class Scissors : public Item {
  65. public:
  66.   Outcome compete(const Item* it) {
  67.     return it->eval(this);
  68.   }
  69.   Outcome eval(const Paper*) const {
  70.     return lose;
  71.   }
  72.   Outcome eval(const Scissors*) const {
  73.     return draw;
  74.   }
  75.   Outcome eval(const Rock*) const {
  76.     return win;
  77.   }
  78.   ostream& print(ostream& os) const {
  79.     return os << "Scissors";
  80.   }
  81. };
  82.  
  83. class Rock : public Item {
  84. public:
  85.   Outcome compete(const Item* it) {
  86.     return it->eval(this);
  87.   }
  88.   Outcome eval(const Paper*) const {
  89.     return win;
  90.   }
  91.   Outcome eval(const Scissors*) const {
  92.     return lose;
  93.   }
  94.   Outcome eval(const Rock*) const {
  95.     return draw;
  96.   }
  97.   ostream& print(ostream& os) const {
  98.     return os << "Rock    ";
  99.   }
  100. };
  101.  
  102. struct ItemGen {
  103.   ItemGen() { srand(time(0)); }
  104.   Item* operator()() {
  105.     switch(rand() % 3) {
  106.       default:
  107.       case 0:
  108.         return new Scissors();
  109.       case 1:
  110.         return new Paper();
  111.       case 2:
  112.         return new Rock();
  113.     }
  114.   }
  115. };
  116.  
  117. struct Compete {
  118.   Outcome operator()(Item* a, Item* b) {
  119.     cout << a << "\t" << b << "\t";
  120.     return a->compete(b);
  121.   }
  122. };
  123.  
  124. int main() {
  125.   const int sz = 20;
  126.   vector<Item*> v(sz*2);
  127.   generate(v.begin(), v.end(), ItemGen());
  128.   transform(v.begin(), v.begin() + sz, 
  129.     v.begin() + sz, 
  130.     ostream_iterator<Outcome>(cout, "\n"), 
  131.     Compete());
  132.   purge(v);
  133. } ///:~
  134.